#include "types.h"
#include "config.h"
#include "atomic.h"
#include "sleeplock.h"
#include "riscv.h"
#include "fs.h"
#include "console.h"
#include "buf.h"
#include "fs_disk.h"
#include "memory.h"
// struct {
//   spinlock_t lock;
//   struct buf buf[NBUF];

//   // Linked list of all buffers, through prev/next.
//   // Sorted by how recently the buffer was used.
//   // head.next is most recent, head.prev is least.
//   struct buf head;
// } bcache;


// // Look through buffer cache for block on device dev.
// // If not found, allocate a buffer.
// // In either case, return locked buffer.
// static struct buf*
// bget(uint dev, uint blockno)
// {
//   struct buf *b;

//   acquire(&bcache.lock);

//   // Is the block already cached?
//   for(b = bcache.head.next; b != &bcache.head; b = b->next){
//     if(b->dev == dev && b->blockno == blockno){
//       b->refcnt++;
//       release(&bcache.lock);
//       acquiresleep(&b->lock);
//       return b;
//     }
//   }

//   // Not cached.
//   // Recycle the least recently used (LRU) unused buffer.
//   for(b = bcache.head.prev; b != &bcache.head; b = b->prev){
//     if(b->refcnt == 0) {
//       b->dev = dev;
//       b->blockno = blockno;
//       b->valid = 0;
//       b->refcnt = 1;
//       release(&bcache.lock);
//       acquiresleep(&b->lock);
//       return b;
//     }
//   }
//   panic("bget: no buffers");
// }
static struct buf*
bget(uint dev, uint blockno)
{

  struct buf *b=(void*)pmm_manager.alloc_pages(1);
  initsleeplock(&b->lock, "buffer");
   if(DEBUG_INODE){
    printk("in bget b->lock is hold?  %d lk->lk %p is hold %d\n",b->lock.locked,&(b->lock.lk),b->lock.lk.lock);
  }
  acquiresleep(&b->lock);
  if(DEBUG_INODE){
    printk(" bget finished\n");
  }
   return b;
}
// Return a locked buf with the contents of the indicated block.
struct buf*
bread(uint dev, uint blockno)
{


   struct buf * b = bget(dev, blockno);
   b->dev = dev;
   b->blockno = blockno;
   b->valid = 0;
   b->refcnt = 1;
  if(!b->valid) {
    disk_rw(b, 0);
    b->valid = 1;
  }
  return b;
}


// Write b's contents to disk.  Must be locked.
void
bwrite(struct buf *b)
{
  if(!holdingsleep(&b->lock))
    panic("bwrite");
  disk_rw(b, 1);
}


// Release a locked buffer.
// Move to the head of the most-recently-used list.
void
brelse(struct buf *b)
{
  if(!holdingsleep(&b->lock))
    panic("brelse");

  releasesleep(&b->lock);
}

